Function declaration is also a Programming Syntax that allows us to do the same as with Lambda Expression.
But in additional we can also
● give the Name to that block of code
● use that Name to call that block of code
● use Named Parameters when calling that block of code (depending on the Language but Kotlin supports this)
If Lambda Expression and Function Declaration have the same Signature then you can store Reference to a Function into
the same Variable. Now you can call that Function in the same way as you would the Lambda Expression, by using that
Variable's Name (but without using Named Parameters).
You can think of Function as a Wrapper around Lambda Expression allowing you to assign a name to a Lambda Expression
and call Lambda Expression with Named Parameters. But when you store Function reference into a Variable then when
using this Variable your Function starts behaving the same as an Lambda Expression (you can't have Named Parameters).
Function Declaration
//DECLARE FUNCTION.
fun greet (name:String, age:Int = 20) : (String) { return("$name is $age years old.") } //Block Syntax
fun greet (name:String, age:Int) : (String) = "$name is $age years old." //Assignment Syntax
//CALL FUNCTION.
greet(name="John", age=50) //Named Parameters
greet("John" , 50) //Indexed Parameters
Such Variables need to be declared to accept Function Data Type specific to the Closure we want to store.
Function Data Type (also known as Signature) defines Data Types of Input Parameters and Return Value.
These can be inferred from the Closure Signature (so you don't need to explicitly specify them in Variable declaration).
But once Closure is stored into Variable, this Variable is set to accept only this Function Data Type so you can't store in it
other Data Types or Functions with different Signatures.
Variables that accept Function Data Type can store Closure, Function & Anonymous Function with the same Signature.
To store Function into Variable you actually have to store a reference to a Function using "::" operator as a prefix before
the Function name: closureVariable = ::greet. You can now use Variable to call Function. But you can't use Named
Parameters anymore because this information is not stored into Variable (it is part of Function Declaration).
Declare Variable that holds specific Function Data Type
var closureVariable : (String, Int) -> (String) //Function that accepts 2 Parameters & returns String
Store Function Reference into Variable
//DECLARE FUNCTION.
fun greet (name:String, age:Int) : (Unit) { println("$name is $age years old.") }
//DECLARE VARIABLE. (THAT HOLDS SPECIFIC FUNCTION DATA TYPE)
var closureVariable : (String, Int) -> (Unit)
//STORE REFERENCE TO FUNCTION INTO VARIABLE.
closureVariable = ::greet
//CALL FUNCTION THROUGH VARIABLE (NO NAMED PARAMETERS).
closureVariable("John", 20)